package com.hqd.ch03.v35.web.servlet.support;

import com.hqd.ch03.v35.web.http.HttpStatus;
import com.hqd.ch03.v35.web.ui.BindingAwareModelMap;
import com.hqd.ch03.v35.web.ui.ModelMap;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * ModelAndView容器，负责帮ModelAndView采集数据
 */
public class ModelAndViewContainer {
    /**
     * 默认model
     */
    private final ModelMap defaultModel = new BindingAwareModelMap();
    private final Set<String> noBinding = new HashSet<>(4);
    private final Set<String> bindingDisabled = new HashSet<>(4);
    /**
     * Session状态
     */
    private final SessionStatus sessionStatus = new SimpleSessionStatus();
    /**
     * 忽略默认重定向
     */
    private boolean ignoreDefaultModelOnRedirect = false;
    /**
     * 视图
     */
    private Object view;
    /**
     * 重定向数据
     */
    private ModelMap redirectModel;
    private boolean redirectModelScenario = false;
    /**
     * 响应状态
     */
    private HttpStatus status;
    private boolean requestHandled = false;


    public void setIgnoreDefaultModelOnRedirect(boolean ignoreDefaultModelOnRedirect) {
        this.ignoreDefaultModelOnRedirect = ignoreDefaultModelOnRedirect;
    }


    public String getViewName() {
        return (this.view instanceof String ? (String) this.view : null);
    }

    public void setViewName(String viewName) {
        this.view = viewName;
    }


    public Object getView() {
        return this.view;
    }

    public void setView(Object view) {
        this.view = view;
    }

    public boolean isViewReference() {
        return (this.view instanceof String);
    }

    public ModelMap getModel() {
        if (useDefaultModel()) {
            return this.defaultModel;
        } else {
            if (this.redirectModel == null) {
                this.redirectModel = new ModelMap();
            }
            return this.redirectModel;
        }
    }

    private boolean useDefaultModel() {
        return (!this.redirectModelScenario || (this.redirectModel == null && !this.ignoreDefaultModelOnRedirect));
    }

    public ModelMap getDefaultModel() {
        return this.defaultModel;
    }

    public void setRedirectModel(ModelMap redirectModel) {
        this.redirectModel = redirectModel;
    }

    public void setRedirectModelScenario(boolean redirectModelScenario) {
        this.redirectModelScenario = redirectModelScenario;
    }

    public HttpStatus getStatus() {
        return this.status;
    }

    public void setStatus(HttpStatus status) {
        this.status = status;
    }

    public void setBindingDisabled(String attributeName) {
        this.bindingDisabled.add(attributeName);
    }

    public boolean isBindingDisabled(String name) {
        return (this.bindingDisabled.contains(name) || this.noBinding.contains(name));
    }

    public void setBinding(String attributeName, boolean enabled) {
        if (!enabled) {
            this.noBinding.add(attributeName);
        } else {
            this.noBinding.remove(attributeName);
        }
    }

    public SessionStatus getSessionStatus() {
        return this.sessionStatus;
    }

    public boolean isRequestHandled() {
        return this.requestHandled;
    }

    public void setRequestHandled(boolean requestHandled) {
        this.requestHandled = requestHandled;
    }

    public ModelAndViewContainer addAttribute(String name, Object value) {
        getModel().addAttribute(name, value);
        return this;
    }

    public ModelAndViewContainer addAttribute(Object value) {
        getModel().addAttribute(value);
        return this;
    }

    public ModelAndViewContainer addAllAttributes(Map<String, ?> attributes) {
        getModel().addAllAttributes(attributes);
        return this;
    }

    public ModelAndViewContainer mergeAttributes(Map<String, ?> attributes) {
        getModel().mergeAttributes(attributes);
        return this;
    }

    public ModelAndViewContainer removeAttributes(Map<String, ?> attributes) {
        if (attributes != null) {
            for (String key : attributes.keySet()) {
                getModel().remove(key);
            }
        }
        return this;
    }

    public boolean containsAttribute(String name) {
        return getModel().containsAttribute(name);
    }


}
